#pragma once
#include<functional>
#include"Socket.h"
#include"InetAddress.h"
#include"Channel.h"
#include"EventLoop.h"
#include"Buffer.h"
#include<memory>
#include<atomic>

class Channel;
class EventLoop;
class Epoll;

class Connection: public std::enable_shared_from_this<Connection>
{
private:
    // Acceptor对应的事件循环，在构造函数中传入。生命周期不属于当前类管理
    EventLoop *loop_;
    // 与客户端通信的socket,在外部创建，但是由本类管理，所以由销毁
    // todo: 既然这样，为什么不由本类创建这个socket呢？？？？
    Socket *clientsock_;
    // =Acceptor对应的channel，在构造函数中创建
    Channel *clientchannel_;
    // 接受缓冲区
    Buffer inputbuffer_;
    // 发送缓冲区
    Buffer outputbuffer_;
    // 客户端连接是否断开，如果断开，设置为true
    std::atomic_bool disconnect_;
    // 关闭fd的回调函数，将回调TCPServer::closeconnection()
    std::function<void(std::shared_ptr<Connection>)> closecallback_;
    // fd发生了错误的回调函数，将回调TCPServer::errorconnection()
    std::function<void(std::shared_ptr<Connection>)> errorcallback_;
    // 处理报文的回调函数，将回调TCPServer::message()
    std::function<void(std::shared_ptr<Connection>, std::string&)> onmessagecallback_;
    // 发送数据完成后的回调函数，将回调TCPServer::sendcomplete()
    std::function<void(std::shared_ptr<Connection>)> sendcompletecallback_;
public:
    Connection(EventLoop *loop, Socket *clientsock);
    ~Connection();
    // 返回 fd_ 成员
    int fd() const;
    // 返回ip成员的值
    std::string ip();
    // 返回port成员的值
    uint16_t port();
    // 处理客户端发送过来的消息
    void onmessage();
    // TCP连接关闭的回调函数，供Channel回调
    void closecallback();
    // TCP连接错误的回调函数，供Channel回调
    void errorcallback();
    // 处理写事件时的回调函数，此时是真正发送数据给TCP缓冲区，供Channel回调
    void writecallback();
    // 设置closecallback_回调函数
    void setclosecallback(std::function<void(std::shared_ptr<Connection>)> fn);
    // 设置errorcallback_回调函数
    void seterrorcallback(std::function<void(std::shared_ptr<Connection>)> fn);
    // 设置onmessagecallback_回调函数
    void setonmessagecallback(std::function<void(std::shared_ptr<Connection>, std::string&)> fn);
    // 设置sendcompletecallback_回调函数
    void setsendcompletecallback(std::function<void(std::shared_ptr<Connection>)> fn);
    // 向缓冲区写入数据
    void send(const char*data, size_t size);
};